package com.meiyuetao.myt.sale.service;

import java.util.Date;
import java.util.Map;

import lab.s2jh.bpm.service.ActivitiService;
import lab.s2jh.core.dao.BaseDao;
import lab.s2jh.core.service.BaseService;
import lab.s2jh.core.service.Validation;
import lab.s2jh.core.util.DateUtils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.meiyuetao.myt.core.constant.VoucherStateEnum;
import com.meiyuetao.myt.core.constant.VoucherTypeEnum;
import com.meiyuetao.myt.finance.entity.AccountInOut;
import com.meiyuetao.myt.finance.service.AccountInOutService;
import com.meiyuetao.myt.md.dao.CommodityDao;
import com.meiyuetao.myt.md.entity.Commodity;
import com.meiyuetao.myt.sale.dao.SaleDeliveryDetailDao;
import com.meiyuetao.myt.sale.dao.SaleReturnDao;
import com.meiyuetao.myt.sale.entity.SaleDeliveryDetail;
import com.meiyuetao.myt.sale.entity.SaleReturn;
import com.meiyuetao.myt.sale.entity.SaleReturn.SaleReturnTypeEnum;
import com.meiyuetao.myt.sale.entity.SaleReturnDetail;
import com.meiyuetao.myt.stock.dao.StorageLocationDao;
import com.meiyuetao.myt.stock.entity.CommodityStock;
import com.meiyuetao.myt.stock.entity.StockInOut;
import com.meiyuetao.myt.stock.entity.StorageLocation;
import com.meiyuetao.myt.stock.service.CommodityStockService;
import com.meiyuetao.myt.stock.service.StockInOutService;

@Service
@Transactional
public class SaleReturnService extends BaseService<SaleReturn, Long> {

    @Autowired
    private SaleReturnDao saleReturnDao;
    @Autowired
    private CommodityDao commodityDao;
    @Autowired
    private StorageLocationDao storageLocationDao;

    @Autowired
    private SaleReturnDetailService saleReturnDetailService;

    @Autowired(required = false)
    private ActivitiService activitiService;

    @Autowired
    private CommodityStockService commodityStockService;
    @Autowired
    private StockInOutService stockInOutService;
    @Autowired
    private SaleDeliveryDetailDao saleDeliveryDetailDao;
    @Autowired
    private AccountInOutService accountInOutService;

    @Override
    protected BaseDao<SaleReturn, Long> getEntityDao() {
        return saleReturnDao;
    }

    @Override
    public SaleReturn save(SaleReturn entity) {
        for (SaleReturnDetail srd : entity.getSaleReturnDetails()) {
            saleReturnDetailService.save(srd);
        }
        return super.save(entity);
    }

    private void saveDetails(SaleReturn entity) {
        /*
         * BigDecimal commodityCostAmount = BigDecimal.ZERO; for
         * (SaleDeliveryDetail sdd : entity.getSaleDeliveryDetails()) {
         * sdd.setSaleDelivery(entity);
         * 
         * CommodityStock commodityStock = findCommodityCommodityStock(sdd);
         * sdd.setCostPrice(commodityStock.getCostPrice());
         * sdd.setCostAmount(commodityStock
         * .getCostPrice().multiply(sdd.getQuantity()));
         * 
         * commodityCostAmount = commodityCostAmount.add(sdd.getCostAmount());
         * 
         * if (entity.getSubmitDate() != null) { BoxOrderDetailCommodity bodc =
         * null; if (sdd.getBoxOrderDetailCommodity() != null) { bodc =
         * boxOrderDetailCommodityDao
         * .findOne(sdd.getBoxOrderDetailCommodity().getId());
         * Validation.isTrue(sdd.getQuantity().equals(bodc.getQuantity()),
         * "如果是关联订单行项商品，数量必须一致"); }
         * 
         * } }
         * 
         * entity.setCommodityCostAmount(commodityCostAmount);
         * entity.setTotalCostAmount
         * (commodityCostAmount.add(entity.getLogisticsAmount() == null ?
         * BigDecimal.ZERO : entity.getLogisticsAmount()));
         */
    }

    public void bpmCreate(SaleReturn entity, Map<String, Object> variables) {
        saveDetails(entity);
        saleReturnDao.save(entity);
        activitiService.startProcessInstanceByKey("BPM_SALE_RETURN", entity);
    }

    public void bpmUpdate(SaleReturn entity, String taskId, Map<String, Object> variables) {
        saveDetails(entity);
        saleReturnDao.save(entity);
        activitiService.completeTask(taskId, variables);
    }

    private CommodityStock findCommodityCommodityStock(SaleReturnDetail sdd) {
        Commodity commodity = commodityDao.findOne(sdd.getCommodity().getId());
        StorageLocation storageLocation = storageLocationDao.findOne(sdd.getStorageLocation().getId());
        String batchNo = sdd.getBatchNo();
        CommodityStock commodityStock = commodityStockService.findBy(commodity, storageLocation, batchNo);
        Validation.isTrue(commodityStock != null, "须先初始化维护库存数据: 商品=[" + commodity.getDisplay() + "],库存地=[" + storageLocation.getDisplay() + "],批次号=[" + batchNo + "]");
        Validation.isTrue(commodityStock.getCostPrice() != null && commodityStock.getCostPrice().doubleValue() > 0, "成本价格无效: 商品=[" + commodity.getDisplay() + "],库存地=["
                + storageLocation.getDisplay() + "],批次号=[" + batchNo + "],成本价=[" + commodityStock.getCostPrice() + "]");
        return commodityStock;
    }

    private StockInOut buildDefaultStockInOut(SaleReturn saleReturn, SaleReturnDetail srd) {
        CommodityStock commodityStock = findCommodityCommodityStock(srd);
        StockInOut stockInOut = new StockInOut(saleReturn.getVoucher(), srd.getSubVoucher(), VoucherTypeEnum.TH, commodityStock);
        return stockInOut;
    }

    /**
     * 供工作流在所有审批完成后的回调接口
     */
    public void bpmAuditPost(SaleReturn entity) {
        entity.setAuditDate(new Date());
        entity.setLastOperationSummary("审核完结:" + DateUtils.formatTime(new Date()));
        entity.setVoucherState(VoucherStateEnum.POST);
        for (SaleReturnDetail srd : entity.getSaleReturnDetails()) {
            if (!SaleReturnTypeEnum.REP.equals(entity.getSaleReturnType()) && !Boolean.TRUE.equals(srd.getScrapped())) {
                /*
                 * CommodityStock commodityStock =
                 * commodityStockService.findBy(srd.getCommodity(),
                 * srd.getStorageLocation(), srd.getBatchNo());
                 * commodityStock.setCurStockAmount
                 * (commodityStock.getCurStockAmount
                 * ().add(srd.getCostAmount()));
                 * commodityStock.setCurStockQuantity
                 * (commodityStock.getCurStockQuantity
                 * ().add(srd.getQuantity()));
                 * commodityStock.setCostPrice(commodityStock
                 * .getCurStockAmount().divide(
                 * commodityStock.getCurStockQuantity(), 2,
                 * RoundingMode.HALF_DOWN));
                 */
                StockInOut stockInOut = buildDefaultStockInOut(entity, srd);
                stockInOut.setDiffQuantity(srd.getQuantity());
                stockInOut.setDiffStockAmount(srd.getCostAmount());
                stockInOut.setOperationSummary("退货入库");
                stockInOutService.saveCascade(stockInOut);
                SaleDeliveryDetail sdd = srd.getSaleDeliveryDetail();
                if (sdd != null) {
                    sdd.setReturnQuantity(sdd.getQuantity().add(srd.getQuantity()));
                    saleDeliveryDetailDao.save(sdd);
                }

            }
        }
        saleReturnDao.save(entity);
        /*
         * // List<AccountInOut> accountInOuts = Lists.newArrayList();
         * //借：6401=主营业务成本 AccountInOut accountInOut =
         * buildDefaultAccountInOut(entity);
         * accountInOut.setAccountSubjectCode("6402");
         * accountInOut.setAccountSummary("退赔损耗");
         * accountInOut.setAmount(entity.getTotalLossAmount());
         * accountInOut.setAccountDirection(true);
         * accountInOuts.add(accountInOut);
         * 
         * accountInOutService.saveBalance(accountInOuts);
         */

    }

    private AccountInOut buildDefaultAccountInOut(SaleReturn entity) {
        AccountInOut accountInOut = new AccountInOut();
        accountInOut.setVoucher(entity.getVoucher());
        accountInOut.setVoucherType(VoucherTypeEnum.TH);
        accountInOut.setPostingDate(entity.getVoucherDate());
        return accountInOut;
    }
}
